/*
 * @Author: underMoonzs 1994186472@qq.com
 * @Date: 2025-08-25 22:31:04
 * @LastEditors: underMoonzs 1994186472@qq.com
 * @LastEditTime: 2025-10-14 23:43:10
 * @FilePath: \lyshjpt\src\views\biz\utils\layerLoader.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import Point from "ol/geom/Point";
import Feature from "ol/Feature";
import {
  createPointStyleFunction,
  createGeojsonStyleFunction,
} from "./layerStyle";
import GeoJSON from "ol/format/GeoJSON";

// 添加Heatmap的导入
import HeatmapLayer from "ol/layer/Heatmap.js";
// 添加WMS图层相关导入
import { TileWMS } from "ol/source";
import TileLayer from "ol/layer/Tile";

/**
 * 添加简化格式的点要素到数据源
 * @param {VectorSource} source - 矢量数据源
 * @param {Array} points - 点数据数组 [{name, longitude, latitude}]
 * @param {string} projection - 投影坐标系
 * @param {string} layerType - 图层类型
 */
function addPointFeatures(source, points, projection, layerId = "default") {
  if (!Array.isArray(points)) return;

  // 创建样式函数
  const styleFunction = createPointStyleFunction(layerId);

  points.forEach((point) => {
    if (point.longitude && point.latitude) {
      // 创建点几何对象
      const geometry = new Point([point.longitude, point.latitude]);

      // 创建要素
      const feature = new Feature({
        geometry: geometry,
        ...point, // 将所有点属性添加到要素中
      });
      feature.set("layerId", layerId);
      // 设置样式
      feature.setStyle(styleFunction);

      source.addFeature(feature);
    }
  });
}

/**
 * 加载GeoJSON数据并创建矢量图层
 * @param {Object} options - 配置选项
 * @param {Object|string} options.data - GeoJSON对象或URL
 * @param {string} [options.layerId='geojson-layer'] - 图层ID
 * @param {Function} [options.style] - 自定义样式函数
 * @param {string} [options.projection='EPSG:4326'] - 投影坐标系
 * @returns {Promise<VectorLayer>} 返回Promise，解析为矢量图层实例
 */
export function loadGeoJsonLayer(options) {
  const { data, layerId = "geojson-layer", projection = "EPSG:4326" } = options;
  const styleFunction = createGeojsonStyleFunction(layerId);

  return new Promise((resolve, reject) => {
    try {
      // 创建矢量数据源
      const source = new VectorSource({ projection });

      // 创建矢量图层
      const vectorLayer = new VectorLayer({
        id: layerId,
        name: layerId,
        source: source,
        style: styleFunction,
      });

      // 使用GeoJSON格式解析器
      const format = new GeoJSON();

      // 判断data是URL还是GeoJSON对象
      if (typeof data === "string") {
        // 如果是URL，通过fetch获取数据
        fetch(data)
          .then((response) => {
            if (!response.ok) {
              throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json();
          })
          .then((geoJsonData) => {
            try {
              // 解析GeoJSON数据并添加到source
              const features = format.readFeatures(geoJsonData, {
                dataProjection: "EPSG:4326",
                featureProjection: projection,
              });
              source.addFeatures(features);

              // 设置图层ID并返回图层
              vectorLayer.set("id", layerId);
              resolve(vectorLayer);
            } catch (parseError) {
              reject(
                new Error(`Error parsing GeoJSON data: ${parseError.message}`)
              );
            }
          })
          .catch((fetchError) => {
            reject(
              new Error(`Failed to fetch GeoJSON data: ${fetchError.message}`)
            );
          });
      } else if (typeof data === "object" && data !== null) {
        // 如果是对象，直接解析
        try {
          const features = format.readFeatures(data, {
            dataProjection: "EPSG:4326",
            featureProjection: projection,
          });
          source.addFeatures(features);

          // 设置图层ID并返回图层
          vectorLayer.set("id", layerId);
          resolve(vectorLayer);
        } catch (parseError) {
          reject(
            new Error(`Error parsing GeoJSON data: ${parseError.message}`)
          );
        }
      } else {
        reject(
          new Error(
            "Invalid data format. Expected GeoJSON object or URL string."
          )
        );
      }
    } catch (error) {
      reject(new Error(`Error creating GeoJSON layer: ${error.message}`));
    }
  });
}

/**
 * 创建点图层
 * @param {Object} options - 图层配置选项
 * @param {Object|string} options.data - GeoJSON数据对象或URL
 * @param {Object} [options.style] - 自定义样式
 * @param {string} [options.projection='EPSG:4326'] - 数据投影坐标系
 * @param {string} [options.layerType='default'] - 图层类型
 * @returns {VectorLayer} 点图层实例
 */
export function createPointLayer(options) {
  console.log("createPointLayer options:", options);
  const { data, layerId, layerType } = options;
  const projection = "EPSG:4326";
  const source = new VectorSource({
    projection,
  });

  addPointFeatures(source, data, projection, layerId);
  // 使用图层级别的样式函数
  const layerStyleFunction = createPointStyleFunction(layerId);

  let l = new VectorLayer({
    id: layerId,
    name: layerId,
    source,
    style: layerStyleFunction,
  });
  l.set("id", layerId);
  return l;
}

/**
 * 从地图中移除指定名称的图层
 * @param {Map} map - OpenLayers地图实例
 * @param {string} layerName - 图层名称
 */
export function removeLayerByName(map, layerName) {
  if (!map || !layerName) return;

  const layers = map.getLayers().getArray();
  layers.forEach((layer) => {
    if (layer.get("name") === layerName) {
      map.removeLayer(layer);
    }
  });
}
export function removeLayerById(map, layerId) {
  if (!map || !layerId) return;

  const layers = map.getLayers().getArray();
  layers.forEach((layer) => {
    if (layer.get("id") === layerId) {
      map.removeLayer(layer);
    }
  });
}

/**
 * 创建热力图要素
 * @param {Array} points - 点数据数组
 * @param {string} projection - 投影坐标系
 * @returns {Array<Feature>} 要素数组
 */
function createHeatmapFeatures(points, projection) {
  if (!Array.isArray(points)) return [];

  return points
    .map((point) => {
      if (point.longitude && point.latitude) {
        // 创建点几何对象
        const geometry = new Point([point.longitude, point.latitude]);

        // 创建要素
        const feature = new Feature({
          geometry: geometry,
          ...point, // 将所有点属性添加到要素中
        });

        return feature;
      }
      return null;
    })
    .filter((feature) => feature !== null);
}

/**
 * 创建热力图图层
 * @param {Object} options - 图层配置选项
 * @param {Array} options.data - 点数据数组 [{name, longitude, latitude, weight}]
 * @param {string} [options.projection='EPSG:4326'] - 数据投影坐标系
 * @param {string} [options.layerId='heatmap'] - 图层ID
 * @param {number} [options.radius=8] - 热力点半径
 * @param {number} [options.blur=15] - 热力图模糊度
 * @param {Array} [options.gradient] - 热力图颜色渐变数组
 * @param {string} [options.weightProperty='weight'] - 权重属性名
 * @returns {HeatmapLayer} 热力图图层实例
 */
export function createHeatmapLayer(options) {
  const {
    data,
    layerId,
    radius = 8,
    blur = 15,
    gradient,
    weightProperty = "weight",
  } = options;
  const projection = "EPSG:4326";
  const source = new VectorSource({
    projection,
    features: createHeatmapFeatures(data, projection),
  });

  const heatmapLayer = new HeatmapLayer({
    source,
    radius,
    blur,
    weight: function (feature) {
      const weight = feature.get(weightProperty);
      return weight !== undefined ? weight : 1;
    },
  });

  // 如果提供了渐变色配置，则设置
  if (gradient && Array.isArray(gradient)) {
    heatmapLayer.setGradient(gradient);
  }

  heatmapLayer.set("id", layerId);
  return heatmapLayer;
}

/**
 * 创建WMS图层
 * @param {Object} options - 图层配置选项
 * @param {string} options.url - WMS服务地址
 * @param {string} options.layerName - WMS图层名称
 * @param {string} [options.layerId] - 图层ID
 * @param {string} [options.projection='EPSG:4326'] - 投影坐标系
 * @param {Object} [options.params] - WMS请求参数
 * @returns {TileLayer} WMS图层实例
 */
export function createWmsLayer(options) {
  const {
    url,
    layerName,
    layerId,
    params = {},
  } = options;
  const projection = "EPSG:4326";
  const wmsSource = new TileWMS({
    url: url,
    params: {
      LAYERS: layerName,
      TILED: true,
      ...params,
    },
    projection: projection,
    serverType: "geoserver",
  });
  const wmsLayer = new TileLayer({
    id: layerId,
    name: layerId,
    source: wmsSource,
  });

  wmsLayer.set("id", layerId);
  return wmsLayer;
}
